package com.ellfors.common.utils

import android.os.Environment
import android.util.Log
import com.ellfors.common.BuildConfig
import com.ellfors.common.app.MyApp
import com.orhanobut.logger.Logger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.BufferedWriter
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import kotlin.math.abs

object LogUtil {
    const val DEFAULT_TAG = "MyTest"
    private val isShowLog = MyApp.isDebug //是否打印log
    private const val SDCARD_LOG_FILE_SAVE_DAYS = 7 // sd卡中日志文件的最多保存天数
    private const val SAVE_NATIVE_FILE_DIR = "/android_log" //原生Log写入路径
    private const val SAVE_FILE_NAME = ".txt" //输出日志的文件后缀
    private const val FILE_SDF = "HH:mm:ss.SSS" //日志文件时间格式
    private const val DIR_SDF = "yyyy-MM-dd"    //日志文件日期格式

    fun logI(tag: String? = DEFAULT_TAG, value: String?) {
        value ?: return
        if (isShowLog) {
            Log.i(tag, value)
        }
        checkWriteFile(tag, value)
    }

    fun logD(tag: String? = DEFAULT_TAG, value: String?) {
        value ?: return
        if (isShowLog) {
            Log.d(tag, value)
        }
        checkWriteFile(tag, value)
    }

    fun logW(tag: String? = DEFAULT_TAG, value: String?) {
        value ?: return
        if (isShowLog) {
            Log.w(tag, value)
        }
        checkWriteFile(tag, value)
    }

    fun logE(tag: String? = DEFAULT_TAG, value: String?) {
        value ?: return
        if (isShowLog) {
            Log.e(tag, value)
        }
        checkWriteFile(tag, value)
    }

    fun logWTF(tag: String? = DEFAULT_TAG, value: String?) {
        value ?: return
        if (isShowLog) {
            Log.wtf(tag, value)
        }
    }

    fun logJson(tag: String? = DEFAULT_TAG, value: String?) {
        value ?: return
        if (isShowLog) {
            Logger.t(tag).json(value)
        }
    }

    private fun checkWriteFile(tag: String?, value: String) {
        //debug模式固定打印与写入
        if (isShowLog) {
            writeLogToFile(tag, value)
            return
        }
        //release模式生产环境不写入，其他写入
        val curHost = BuildConfig.FLAVOR_env
        if (curHost != "product") {
            writeLogToFile(tag, value)
        }
    }

    /**
     * 打开日志文件并写入日志
     */
    private fun writeLogToFile(tag: String?, value: String) {
        MyApp.appScope.launch {
            withContext(Dispatchers.IO) {
                // 新建或打开日志文件
                val fileDir = SAVE_NATIVE_FILE_DIR
                val needWriteFile = Date().formatDate(DIR_SDF)
                val date = Date().formatDate(FILE_SDF)
                val needWriteMessage = "[${date}] [${tag}] $value"
                val fileParent = MyApp.context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)
                val dirsFile = File("$fileParent$fileDir")
                if (!dirsFile.exists()) {
                    dirsFile.mkdirs()
                }
                val file = File(dirsFile.toString(), "${needWriteFile}$SAVE_FILE_NAME")
                if (!file.exists()) {
                    try {
                        //在指定的文件夹中创建文件
                        file.createNewFile()
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
                try {
                    // 后面这个参数代表是不是要接上文件中原来的数据，不进行覆盖
                    val filerWriter = FileWriter(file, true)
                    val bufWriter = BufferedWriter(filerWriter)
                    bufWriter.write(needWriteMessage)
                    bufWriter.newLine()
                    bufWriter.close()
                    filerWriter.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
        }
    }

    /**
     * 删除指定的日志文件
     */
    fun deleteLogFile() {
        MyApp.appScope.launch {
            withContext(Dispatchers.IO) {
                val fileParent = MyApp.context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)
                //native
                val nativeDir = File("$fileParent$SAVE_NATIVE_FILE_DIR")
                if (nativeDir.exists()) {
                    nativeDir.listFiles()?.forEach {
                        if (it.exists() && it.checkFileDel()) {
                            it.delete()
                        }
                    }
                }
            }
        }
    }

    /**
     * 校验log文件是否需要删除
     */
    private fun File?.checkFileDel(): Boolean {
        this ?: return false
        return try {
            val time = name.substring(0, DIR_SDF.length)
            val calendar = Calendar.getInstance()
            val dateFormat = SimpleDateFormat(DIR_SDF, Locale.getDefault())
            val targetDate = dateFormat.parse(time)
            val diff = abs(calendar.time.time - (targetDate?.time ?: 0))
            val daysDiff = (diff / (24 * 60 * 60 * 1000)).toInt()
            daysDiff > SDCARD_LOG_FILE_SAVE_DAYS
        } catch (e: Exception) {
            false
        }
    }

    /**
     * 格式化日期
     */
    private fun Date.formatDate(pattern: String): String {
        return SimpleDateFormat(pattern, Locale.getDefault()).format(this)
    }
}